import 'dart:io';

import 'package:cher_flare/common/models/ly_user_works_model.dart';
import 'package:cher_flare/config/url_api.dart';
import 'package:cher_flare/http/http_utils.dart';
import 'package:cher_flare/modules/login/models/ly_login_info_manager.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../common/models/ly_broadcaster_model.dart';
import 'dart:convert';
import 'package:flutter/services.dart' show rootBundle;
import 'dart:math';

import '../common/models/ly_video_model.dart';

class LYDataManager {
  static String worksKey = "works_key";
  static String userKey = "user_key";
  static String videosKey = "videos_key";
  LYDataManager._internal();
  static final LYDataManager _instance = LYDataManager._internal();
  static LYDataManager get share {
    final userId = LYLoginInfoManager.getInstance.loginModel?.userInfo;
    worksKey = '${userId}_works_key';
    userKey = '${userId}_user_key';
    videosKey = '${userId}_videos_key';
    return _instance;
  }

  List<LyVideoModel> videosList = [];
  List<LYWorksModel> allUserWorks = [];
  List<LyBroadcasterModel> users = [];

  Future<void> blackUser(String? userId) async {
    Map<String, String> parameters = {
      'broadcasterId': userId ?? '',
      'complainCategory': "Block"
    };
    final response = await HttpUtils.getInstance
        .post(URLApi.insertBlockRecord, data: parameters);
    await HttpUtils.getInstance
        .post(URLApi.unfriend, data: {'followUserId': userId});
    await blackVideoUser(userId);
    await blackWorksUser(userId);
  }

  Future<void> unBlackUser(String? userId) async {
    await unBlackWorksUser(userId);
    await unBlackVideoUser(userId);
  }

  Future<void> unBlackVideoUser(String? userId) async {
    if (videosList.isEmpty) {
      return;
    }
    for (final model in videosList) {
      if (model.userId == userId) {
        model.isBlack = false;
      }
    }
    final jsonObject = videosList.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(videosKey, jsonEncode(jsonObject));
  }

  Future<void> blackVideoUser(String? userId) async {
    final res =
        videosList.firstWhereOrNull((element) => element.userId == userId);
    if (res == null) {
      return;
    }
    if (videosList.isNotEmpty) {
      for (final model in videosList) {
        if (model.userId == userId) {
          model.isBlack = true;
        }
      }
    }
    final jsonObject = videosList.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(videosKey, jsonEncode(jsonObject));
  }

  Future<void> unBlackWorksUser(String? userId) async {
    for (final model in allUserWorks) {
      if (model.userId == userId) {
        model.isBlack = false;
      }
    }
    final jsonObject = allUserWorks.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(worksKey, jsonEncode(jsonObject));
  }

  Future<void> blackWorksUser(String? userId) async {
    if (allUserWorks.isNotEmpty && userId != null) {
      for (final model in allUserWorks) {
        if (model.userId == userId) {
          model.isBlack = true;
        }
      }
    }
    final jsonObject = allUserWorks.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(worksKey, jsonEncode(jsonObject));
  }

  Future<LyBroadcasterModel?> searchUser(String userId) async {
    if (users.isEmpty) {
      await loadUsers();
    }
    final userModel = users.firstWhereOrNull((element) {
      return element.userId == userId;
    });
    return userModel;
  }

  Future<void> updateUserInfo() async {
    final jsonObject = users.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(userKey, jsonEncode(jsonObject));
    return;
  }

  void updateLocalWorksData({LYWorksModel? model}) async {
    if (model != null) {
      final index =
          allUserWorks.indexWhere((element) => element.id == model.id);
      if (index != -1) {
        allUserWorks.replaceRange(index, index, [model]);
      }
    }
    final jsonObject = allUserWorks.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(worksKey, jsonEncode(jsonObject));
  }

  Future<void> deleteWorks(LYWorksModel model) async {
    allUserWorks.remove(model);
    final jsonObject = allUserWorks.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(worksKey, jsonEncode(jsonObject));
    return;
  }

  Future<void> addWorksData(LYWorksModel model) async {
    allUserWorks.insert(0, model);
    final jsonObject = allUserWorks.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(worksKey, jsonEncode(jsonObject));
    return;
  }

  Future<List<LYWorksModel>?> loadMyWorks() async {
    if (allUserWorks.isEmpty) {
      await initUserAndWorksData();
    }
    final userId = LYLoginInfoManager.getInstance.loginModel?.userInfo?.userId;
    return allUserWorks.where((element) => element.userId == userId).toList();
  }

  Future<void> initUserAndWorksData() async {
    if (allUserWorks.isNotEmpty) {
      return;
    }
    EasyLoading.show();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final jsonString = prefs.getString(worksKey);
    if (jsonString != null && jsonString.isNotEmpty) {
      final jsonResponse = jsonDecode(jsonString);
      List<LYWorksModel> allWorks = [];
      for (final json in jsonResponse) {
        final worksModel = LYWorksModel.fromJson(json);
        allWorks.add(worksModel);
      }
      allUserWorks = allWorks;
      if (allUserWorks.isNotEmpty) {
        EasyLoading.dismiss();
        return;
      }
    }

    await _makeUserAndWorksData();
    EasyLoading.dismiss();
  }

  Future<void> _makeUserAndWorksData() async {
    if (users.isEmpty) {
      await loadUsers();
    }
    if (users.isEmpty) {
      _makeUserAndWorksData();
      return;
    }
    final userWorks = await loadUserWorksData();
    List<LYWorksModel> allWorks = [];
    int index = 0;
    for (final worksModel in userWorks) {
      final user = users[index];
      final works = worksModel.works;
      if (works != null && works.isNotEmpty) {
        for (final item in works) {
          item.userId = user.userId;
          item.nickname = user.nickname;
          item.avatar = user.avatar;
          item.upvote = Random().nextInt(20);
          allWorks.add(item);
        }
      }
      index++;
    }
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final jsonObject = allWorks.map((v) => v.toJson()).toList();
    prefs.setString(worksKey, jsonEncode(jsonObject));
    allUserWorks = allWorks;
  }

  void updateVideoData({LyVideoModel? model}) async {
    if (model != null) {
      final index = videosList.indexWhere((element) => element.id == model.id);
      if (index != -1) {
        videosList.replaceRange(index, index, [model]);
      }
    }
    final jsonObject = videosList.map((v) => v.toJson()).toList();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(videosKey, jsonEncode(jsonObject));
  }

  Future<void> initVideosData() async {
    if (videosList.isNotEmpty) {
      return;
    }
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final videosJson = prefs.getString(videosKey);
    if (videosJson != null && videosJson.isNotEmpty) {
      final jsonResponse = jsonDecode(videosJson);
      for (final json in jsonResponse) {
        final model = LyVideoModel.fromJson(json);
        // debugPrint('=====userId======${model.userId}');
        videosList.add(model);
      }
      if (videosList.isNotEmpty) {
        return;
      }
    }

    await _makeVideosData();
  }

  Future<void> _makeVideosData() async {
    if (users.isEmpty) {
      await loadUsers();
    }
    final parameters = [];
    for (int i = 1; i <= 15; i++) {
      Map<String, String> map = {};
      map['mediaPath'] = "CherFlare/video/$i.mp4";
      map["mediaType"] = "video";
      parameters.add(map);
    }
    final response =
        await HttpUtils.getInstance.post(URLApi.mediaSearch, data: parameters);
    final videos = await loadVideosData();
    int index = 0;
    for (final model in videos) {
      final user = users[index];
      final json = response.data[index];
      model.userId = user.userId;
      model.nickname = user.nickname;
      model.avatar = user.avatar;
      model.mediaUrl = json['mediaUrl'];
      videosList.add(model);
      index++;
    }
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final jsonObject = videosList.map((v) => v.toJson()).toList();
    prefs.setString(videosKey, jsonEncode(jsonObject));
    return;
  }

  Future<List<LyVideoModel>> loadVideosData() async {
    String jsonString = await rootBundle.loadString('assets/files/videos.json');
    final jsonResponse = jsonDecode(jsonString);
    List<LyVideoModel> videos = [];
    for (final json in jsonResponse) {
      final videoModel = LyVideoModel.fromJson(json);
      videos.add(videoModel);
    }
    return videos;
  }

  Future<List<LyUserModel>> loadUserWorksData() async {
    String jsonString = await rootBundle.loadString('assets/files/works.json');
    final jsonResponse = jsonDecode(jsonString);
    List<LyUserModel> works = [];
    for (final json in jsonResponse) {
      final worksModel = LyUserModel.fromJson(json);
      works.add(worksModel);
    }
    return works;
  }

  Future<void> loadUsers() async {
    if (users.isNotEmpty) {
      return;
    }
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final jsonString = prefs.getString(userKey);
    if (jsonString != null) {
      final json = jsonDecode(jsonString);
      if (json is List) {
        for (final json in json) {
          final model = LyBroadcasterModel.fromJson(json);
          users.add(model);
        }
        return;
      }
    }
    users = await requestUserList();
  }

  Future<List<LyBroadcasterModel>> requestUserList({int page = 1}) async {
    Map<String, dynamic> parameters = {
      "category": "Popular", // 分类固定传Popular
      "isPageMode": true,
      "isRemoteImageUrl": true, // 必须为true 否则返回的头像链接需要拼接
      "limit": 20,
      "page": page,
      "tag": "All",
    };
    final response = await HttpUtils.getInstance
        .post(URLApi.broadcasterWall, data: parameters);
    List<LyBroadcasterModel> list = [];
    if (response.data is List) {
      for (final json in response.data) {
        final model = LyBroadcasterModel.fromJson(json);
        list.add(model);
      }
    }
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(userKey, jsonEncode(response.data));
    return list;
  }

  void removeAllData() async {
    videosList.clear();
    users.clear();
    allUserWorks.clear();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.remove(worksKey);
    prefs.remove(userKey);
    prefs.remove(videosKey);
    removeImages();
    removeVoices();
  }

  void removeImages() async {
    Directory applicationDir = await getApplicationDocumentsDirectory();
    final path = Directory("${applicationDir.path}/images");
    bool isDirExist = await path.exists();
    if (isDirExist) {
      path.deleteSync(recursive: true);
    }
  }

  void removeVoices() async {
    Directory applicationDir = await getApplicationDocumentsDirectory();
    final path = Directory("${applicationDir.path}/voices");
    bool isDirExist = await path.exists();
    if (isDirExist) {
      path.deleteSync(recursive: true);
    }
  }
}
